var ie = window.navigator.userAgent.indexOf ("MSIE") != -1;
var TreeIcons = {
    ImagePath      : 'img',
    FolderIcon     : 'folder.gif',
    FolderOpenIcon : 'folderopen.gif',
    ItemIcon       : 'page.gif',
    JoinLine       : 'join.gif',
    JoinBottom     : 'joinbottom.gif',
    Plus           : 'plus.gif',
    PlusBottom     : 'plusbottom.gif',
    NoLinePlus     : 'nolines_plus.gif',
    Minus          : 'minus.gif',
    MinusBottom    : 'minusbottom.gif',
    NoLineMinus    : 'nolines_minus.gif',
    Root           : 'base.gif',
    Line           : 'line.gif'
};
function TreeNode (id, caption, href)
{
	
    var parent = null;
	var children = [];
	var element;
	var root;
	var opened = false, leaf = true;
	var indexOfParent;
    var self = this;
	var deep = 0;

    this.id = id;
    this.installed = false;
    this.handlerIcon = null;
    this.folderIcon = null;
    this.label = null;
    this.childRows = [];
    this.tree = null;
    this.selected = false;
    caption = caption.replace (/&/g, "&amp;");

    init ();
    this.setRoot = function (value) { root = value; }
	this.isRoot = function () { return root; }
	this.setHref = function (value, target) {
        if (!this.label) this.label = document.createElement ("span");
        this.label.innerHTML = "<a href='" + value + "'" +
                               (target ? " targer='" + target + "'" : "") +
                               ">" + caption + "</a>";
    }  
	this.getIndexOfParent = function () { return indexOfParent; }
    this.setIndexOfParent = function (value) { indexOfParent = value; }
    this.setParent = function (value) { parent = value; }
    this.getParent = function () { return parent; }
    this.getChildren = function () { return children; } 
	this.getDeep = function () { return deep; }
	this.setDeep = function (value) { deep = value; }
    this.getCaption = function () { return caption; }
	this.setCaption = function (value) {
	    caption = value.replace (/&/g, "&amp;");
		this.label.innerHTML = href ? "<a href='" + href + "'>" + caption + "</a>" : value;
		this.label.parentNode.title = value;
//        caption = value;
    }
    this.isOpen = function () { return opened; }
    this.getElement = function () { return element; }
    this.setLeaf = function (value)
    {
        leaf = value;
        if (leaf) {
            this.folderIcon.src = TreeIcons.ImagePath + "/" + TreeIcons.ItemIcon;
            this.label.parentNode.ondblclick = "";
            this.handlerIcon.src = TreeIcons.ImagePath + '/' + (this.getNextSbling() ? TreeIcons.JoinLine : TreeIcons.JoinBottom);
            this.handlerIcon.style.cursor = "default";
            this.handlerIcon.onclick = "";
            while (element.rows.length > 1) element.deleteRow (1);
            for (var i = 0; i < children.length; i ++) {
                delete children [i];
                children [i] = null;
            }
            children.length = 0;
        } else {
            this.folderIcon.src = TreeIcons.ImagePath + '/' + (opened ? TreeIcons.FolderOpenIcon : TreeIcons.FolderIcon);
            this.label.parentNode.ondblclick = function () {
                if (opened) self.close();
                else self.open ();
            };
            this.handlerIcon.src = TreeIcons.ImagePath + '/' + (this.getNextSbling() ?
                                   (opened ? TreeIcons.Minus : TreeIcons.Plus) :
                                   (opened ? TreeIcons.MinusBottom : TreeIcons.PlusBottom));
            this.handlerIcon.style.cursor = "default";
            this.handlerIcon.onclick = __HandlerClicked;
        }
    }
    this.isLeaf = function () { return leaf; }
    this.select = function () {
        this.label.style.backgroundColor = '#5378E8';
        this.label.style.color = 'white';
        this.selected = true;
    }
    this.unselect = function () {
        this.label.style.backgroundColor = '';
        this.label.style.color = '';        
    }
    this.buildPath = function () {
        var array = [];
        var p = this;
        while (p != null) {
            array.push (p);
            p = p.getParent();
        }
        array.reverse();
        return array;
    }
    this.spreadTree = function () {
        for (var i = 0; i < children.length; i ++) {
            children [i].tree = this.tree;
            children [i].spreadTree ();
        }
    }
    this.getNextSbling = function () {
		if (!parent) return null;
        if (parent.getChildren().length <= indexOfParent + 1) return null;
        return parent.getChildren () [indexOfParent + 1];
	}
	this.getPrevSbling = function () {
        if (!parent) return null;
        if (indexOfParent == 0) return null;
        return parent.getChildren ()[indexOfParent - 1];
	}
    this.removeFromParent = function () {
        if (!parent) return;
        parent.removeChild (this);
    }
    this.removeChild = function (child) {
        for (var i = 0; i < children.length; i ++) {
            if (child == children [i]) {
                var prev = child.getPrevSbling ();
                // adjust nodes after the node which deleted.
                element.deleteRow (i + 1);
                for (var j = i; j < children.length - 1; j ++) {
                    children [j] = children [j + 1];
                    children [j].setIndexOfParent (children [j].getIndexOfParent () - 1);
                }
                children.length --;
                // adjust current node.
                if (!root && children.length == 0) {
                    this.folderIcon.src = TreeIcons.ImagePath + "/" + TreeIcons.ItemIcon;
                    this.handlerIcon.src = TreeIcons.ImagePath + "/" + (this.getNextSbling() == null ? TreeIcons.JoinBottom : TreeIcons.JoinLine);
                    this.handlerIcon.onclick = '';
                    this.handlerIcon.style.cursor = 'default';
                    this.setLeaf (true);
                    opened = false;
                }
                // adjust prev sbling
                if (prev)
                    prev.handlerIcon.src = TreeIcons.ImagePath + "/" + (prev.getNextSbling() ?
                                           (prev.isLeaf() ? TreeIcons.JoinLine :
                                           (prev.isOpen() ? TreeIcons.Minus : TreeIcons.Plus)) :
                                           (prev.isLeaf() ? TreeIcons.JoinBottom :
                                           (prev.isOpen() ? TreeIcons.MinusBottom : TreeIcons.PlusBottom)));
                if (this.tree && this.tree.getSelectedNode() == child) this.tree.setSelectedNode (null); 
                return;
            }
        }
    }
    this.close = function () {
        if (this.tree) {
            var handler = this.tree.getCloseListener();
            if (this.tree.isEventEnabled() && handler) {
                setTimeout (function () {
                    handler ({tree: self.tree, source: self});
                }, 0);
            }
        }
        for (var i = 0; i < this.childRows.length; i ++)
            this.childRows [i].style.display = 'none';
        this.handlerIcon.src = TreeIcons.ImagePath + "/" + (root ? TreeIcons.NoLinePlus :
                               indexOfParent == self.getParent().getChildren().length - 1 ?
                               TreeIcons.PlusBottom : TreeIcons.Plus);
        if (!root) this.folderIcon.src = TreeIcons.ImagePath + "/" + TreeIcons.FolderIcon;
        opened = false;
    }

    this.open = function () {
        if (this.tree) {
            var handler = this.tree.getOpenListener();
            if (this.tree.isEventEnabled() && handler) {
                setTimeout (function () {
                    handler ({tree: self.tree, source: self});
                }, 0);
            }
        }
        for (var i = 0; i < this.childRows.length; i ++)
            this.childRows [i].style.display = ie ? 'block' : 'table-row';
        this.handlerIcon.src = TreeIcons.ImagePath + "/" + (root ? TreeIcons.NoLineMinus :
                               indexOfParent == self.getParent().getChildren().length - 1 ?
                               TreeIcons.MinusBottom : TreeIcons.Minus);
        if (!root) this.folderIcon.src = TreeIcons.ImagePath + "/" + TreeIcons.FolderOpenIcon;
        opened = true;
		if (ie && this.tree)
		{
			this.tree.getRoot ().getElement ().style.width = 
				element.clientWidth + (deep * 18);
		}
    }

    this.openPath = function () {
        var path = this.buildPath ();
        if (this.tree) {
            this.tree.setEventEnabled (false);
            for (var i = 0; i < path.length; i ++) path [i].open ();
            this.tree.setEventEnabled (true);
        }
    }

    this.showLines = function () {
        for (var i = 0; i < this.childRows.length; i ++) {
            var cell = this.childRows [i].cells [0];
            cell.style.backgroundImage = "url('" + TreeIcons.ImagePath + "/" + TreeIcons.Line + "')";
        }
    }

    this.add = function (child) {
        child.setIndexOfParent (children.length);
        child.setParent (this);
        if (this.tree) child.tree = this.tree;
        children.push (child);
        this.setLeaf (false);
        var row = element.insertRow (-1);
        var cell = row.insertCell(-1);
        if (this.getNextSbling() != null)
            cell.style.backgroundImage = "url('" + TreeIcons.ImagePath + "/" + TreeIcons.Line + "')";
        var prev = child.getPrevSbling();
        if (prev != null) {
            prev.showLines();
            prev.handlerIcon.src = TreeIcons.ImagePath + "/" + (prev.isLeaf() ? TreeIcons.JoinLine :
                                   prev.isOpen() ? TreeIcons.Minus : TreeIcons.Plus);
        }

        this.childRows.push (row);
        cell = row.insertCell (-1);
        cell.appendChild (child.getElement());
        if (!opened) {
            var backup = this.tree;
            this.close();
            this.tree = backup;
        }
		child.setDeep (deep + 1);
		if (ie && this.tree)
		{
			this.tree.getRoot ().getElement ().style.width = 
				element.clientWidth + (deep * 18);
		}
    }

    function __HandlerClicked () {
        if (opened) self.close ();
        else self.open();
    }

    function init () {
    	
        element = document.createElement("table");
        element.cellPadding = 0;
        element.cellSpacing = 0;
        var row = element.insertRow(-1);
        var cell = row.insertCell(-1);
        self.handlerIcon = document.createElement("img");
        self.handlerIcon.src = TreeIcons.ImagePath + "/" + (leaf ? TreeIcons.JoinBottom : TreeIcons.PlusBottom);
        self.handlerIcon.align = 'absmiddle';
        self.handlerIcon.style.cursor = leaf ? "default" : 'pointer';
        self.handlerIcon.onclick = leaf ? "" : __HandlerClicked;
        cell.appendChild (self.handlerIcon);

        cell = row.insertCell (-1);
        cell.noWrap = true;
		cell.width = "100%";
        self.folderIcon = document.createElement ("img");
        self.folderIcon.src = TreeIcons.ImagePath + "/"+ (root ? TreeIcons.Root :
                              leaf ? TreeIcons.ItemIcon : TreeIcons.FolderIcon);
        self.folderIcon.align = 'absmiddle';
        cell.appendChild (self.folderIcon);
        if (!self.label) self.label = document.createElement ("span");
        self.label.innerHTML = href ? "<a href='" + href + "'>" + caption + "</a>" : caption;
        cell.style.cursor = 'default';
        cell.onclick = function (e) {
            if (self.tree) {
				self.tree.setSelectedNode (self);
				var array = self.tree.getClickListener();
				e = e || window.event;
				var event = {tree:self.tree, source:self, x : e.clientX, y : e.clientY};
				if (self.tree.isEventEnabled()) {
					setTimeout (function () {
						for (var i = 0; i < array.length; i ++) array [i] (event);
					}, 0);
				}
            }
        }
        self.label.oncontextmenu = function (event)
        {
            if (self.tree)
            {
				self.tree.setSelectedNode (self);
                var listener = tree.getOnPopupMenuListener ();
                if (listener) {
                    if (!listener ()) return;
                }

                var popup = self.tree.getPopupMenu ();
                if (!popup) return true;
                var e = event || window.event;
                popup.source = self;
                popup.show (e.clientX, e.clientY);
                return false;
            }
            return true;
        }
        if (!leaf) cell.ondblclick = __HandlerClicked;
        cell.onselectstart = function () { return false; }
        cell.appendChild (self.label);
		cell.title = caption;
    }

    this.toString = function ()
    {
        var s = caption;
        s += " indexOfParent = " + indexOfParent;
        return s;
    }
}

function Tree (root)
{
    var self = this;
    var eventEnable = true;
	var paths = "";
    root.setRoot (true);
    var selectedNode = null, treePath, popup = null;
    var changeListener = null, openListener = null, closeListener = null, clickListner = [];
    var popupListener = null;

    this.isEventEnabled = function () { return eventEnable; }
    this.setEventEnabled = function (value) { eventEnable = value; }

    this.install = function (parent) {
		if (typeof parent == 'string') parent = document.getElementById (parent);
		parent.appendChild (root.getElement ());
        root.folderIcon.src = TreeIcons.ImagePath +"/" + TreeIcons.Root;
        root.handlerIcon.src = TreeIcons.ImagePath + "/" + TreeIcons.NoLinePlus;
        root.tree = this;
        root.spreadTree();
        root.installed = true;
	}

    this.getSelectedNode = function () { return selectedNode; }
    this.setSelectedNode = function (value) {
		if (value == selectedNode) return;
        var oldNode = selectedNode;
        if (selectedNode) selectedNode.unselect ();
        selectedNode = value;
		if (value) {
	        treePath = value.buildPath ();
			selectedNode.select();
		}
		if (eventEnable && changeListener) {
            setTimeout (function () {
                changeListener ({old:oldNode, current:value, sender:self});
            }, 0);
        }
    }
    this.getTreePath = function () { return treePath; }
    this.setTreePath = function (value) {
        treePath = value;
        setSelectedNode (value [value.length - 1]);
    }
	this.getRoot = function () { return root; }
    this.setPopupMenu = function (menu) { popup = menu; }
    this.getPopupMenu = function () { return popup; }

    this.setOnSelectionChangeListener = function (listener) { changeListener = listener; }
    this.setOpenListener = function (listener) { openListener = listener; }
    this.getOpenListener = function () { return openListener; }
    this.setCloseListener = function (listener) { closeListener = listener; }
    this.getCloseListener = function () { return closeListener; }
    this.addClickListener = function (listener) { clickListner.push (listener); }
    this.getClickListener = function () { return clickListner; }
    this.setOnPopupMenuListener = function (listener) { popupListener = listener; }
    this.getOnPopupMenuListener = function () { return popupListener; }
    this.getRealPath = function (){return paths;}
    this.setRealPath=function(path){
    	var tp = path.toString();
		var tps = tp.split(",");
		var path = "";		
		for (var i = 0; i < tps.length; i++) {
			var t = tps[i];
			if (i!=0)	path+=" > "		
			var name = t.substr(0, t.indexOf("indexOf"));			
			name = name.replace(/(^\s*)|(\s*$)/g, "");
//			Logger.debug(name);
			path += name;
		}
		paths = path;
		
    }
}